#ifndef M5d718a6c07ca45e19a2cd5e7ab52430e
#define M5d718a6c07ca45e19a2cd5e7ab52430e
/**
 *   Copyright (c) Rich Hickey. All rights reserved.
 *   The use and distribution terms for this software are covered by the
 *   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
 *   which can be found in the file epl-v10.html at the root of this distribution.
 *   By using this software in any fashion, you are agreeing to be bound by
 * 	 the terms of this license.
 *   You must not remove this notice, or any other, from this software.
 **/

/**
 *   Author: Timothy Baldridge
 **/
#include "IPersistentList.h"
#include <QList>
#include <vector>
#include "ISeq.h"
#include "EmptyList.h"
#include "ASeq.h"
#include "AFn.h"
#include "CjObject.h"



namespace clojure_lang {
    /// <summary>
    /// Represents a persistent list.
    /// </summary>
	class PersistentList :
                 public ASeq, virtual public IPersistentList, virtual public ICounted
	{
        Q_OBJECT
        Q_INTERFACES(clojure_lang::IPersistentList clojure_lang::ICounted)
	private:
        /// <summary>
        /// The first item in the list.
        /// </summary>
                CjObject *_first;
        /// <summary>
        /// The rest of the list.
        /// </summary>
                IPersistentList *_rest;
        /// <summary>
        /// The number of items in the list.
        /// </summary>
		int _count;





	public:
                PersistentList(CjObject *first);

                PersistentList(IPersistentMap *meta, CjObject *first, IPersistentList *rest, int count);
                virtual ~PersistentList(void);

        /// <summary>
        /// Create a list initialized from a given QList.
        /// </summary>
        /// <param name="init">The list to initialize from.</param>
        /// <returns>A list.</returns>
        static IPersistentList *create(QList<CjObject *> *init);

        /// <summary>
        /// Create a list initialized from a given std:list.
        /// </summary>
        /// <param name="init">The list to initialize from.</param>
        /// <returns>A list.</returns>
                Q_INVOKABLE IPersistentList *create(std::vector<CjObject *> *init);
		
		/// <summary>
        /// Peek at the top (first) element in the stack.
        /// </summary>
        /// <returns>The top (first) element.</returns>
                Q_INVOKABLE CjObject *peek();

		/// <summary>
        /// Returns a new stack with the top element popped.
        /// </summary>
        /// <returns>The new stack</returns>
                Q_INVOKABLE IPersistentStack *pop();


                //virtual ISeq *seq();

                Q_INVOKABLE virtual CjObject *first();
                Q_INVOKABLE virtual ISeq *next();

                Q_INVOKABLE CjObject *withMeta(IPersistentMap *meta);

            virtual IPersistentCollection *cons(CjObject *o);
            int count();

            class Ctor : public AFn<PersistentList, EmptyList, IPersistentList>
            {
                CjObject *invoke(IPersistentList *lst);
            };

            static Ctor createEx;

	};
        PersistentList *operator << (PersistentList p, CjObject *obj);

}


#endif
